/**
 * $Id: UnzipJarFile.java 4 2010-09-10 17:02:31Z tanktong $
 * Copyright(C) 2010-2014 xiaonei.com/kaixin.com, All Rights Reserved.
 */
package com.tkiicpp.tank.utils.jar;

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;


/**
 * @author <a href="mailto:kun.tong@opi-corp.com">Tank.Tong</a>
 * @version 1.0 2010-08-05 14:30:16
 * @since 1.0
 */
public class UnzipJarFile {

    private static final String CLASS_SUFFIX = ".class";

    public static void unzipJarFile(File jarFile, File tmpFolder) {
        try {
            ZipInputStream in = new ZipInputStream(new FileInputStream(jarFile));
            DataInputStream dataIn = new DataInputStream(in);
            if (!tmpFolder.exists()) {
                tmpFolder.mkdirs();
                Debugger.debug("Create temporery folder " + tmpFolder.getAbsolutePath());
            }

            ZipEntry entry = in.getNextEntry();
            String name = null;
            File file = null;
            FileOutputStream out = null;

            while (entry != null) {
                name = entry.getName();
                file = new File(tmpFolder, name);

                if (entry.isDirectory()) {
                    file.mkdirs();
                } else {
                    file.createNewFile();
                    out = new FileOutputStream(file);

                    long len = entry.getSize();
                    long total = 0;
                    byte[] data = null;

                    while (total < len) {
                        if (len - total > 1024) {
                            data = new byte[1024];
                        } else {
                            data = new byte[(int) (len - total)];
                        }

                        dataIn.readFully(data);

                        total += data.length;
                        out.write(data);
                    }

                    out.flush();
                    out.close();
                }
                entry = in.getNextEntry();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static Set<String> getClassNamesFromJarFile(File jarFile) {
        Set<String> classNames = new HashSet<String>();

        try {
            JarFile jar = new JarFile(jarFile);

            Enumeration<JarEntry> entries = jar.entries();
            JarEntry entry = null;
            String name = null;

            while (entries.hasMoreElements()) {
                entry = entries.nextElement();
                name = entry.getName();

                if (!entry.isDirectory() && name.endsWith(CLASS_SUFFIX)) {
                    classNames.add(convertClassName(name.substring(0, name.length() - CLASS_SUFFIX.length())));
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return classNames;
    }

    private static String convertClassName(String packageName) {
        return packageName.replaceAll("/", ".");
    }

}
